/***
@licence
***/

package jp.ize.iwp.utils;

// {{{ imports

#if flash9
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.Sprite;
import flash.display.Stage;
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import flash.Error;
#else
import flash.MovieClip;
import flash.TextFormat;
import jp.ize.iwp.avm1.events.MouseEvent;
import jp.ize.iwp.avm1.display.Sprite;
import jp.ize.iwp.avm1.display.Stage;
import jp.ize.iwp.avm1.text.TextField;
#end

import jp.ize.iwp.RuntimeEngine;

// }}}
/**
* DebugUtil クラスです。<br />
*
*/
class DebugUtil extends Sprite
{
	// {{{ properties

	public static var debugger:DebugUtil;
	private var w:Float;
	private var h:Float;
	private var tf:TextField;
	private var isResizing:Bool;
	private var d1:Sprite;
	private var sp1:Sprite;
	private var sp2:Sprite;
	private var sp3:Sprite;
	private var sp4:Sprite;
	private var sp5:Sprite;
	private var sp6:Sprite;

	// }}}
	// {{{ public static function init() : Void
	/**
	* Debug環境を初期化します。
	* trace() 文を利用する前に呼出す必要があります。
	*/
	public static function init() : Void
	{
		#if flash9
		debugger = new DebugUtil();
		if ( RuntimeEngine.base!=null ) {
			RuntimeEngine.getStage().addChild(debugger);
		} else {
			throw new Error("RuntimeEngine not initialized!");
		}
		debugger.create();
		#else
		debugger = new DebugUtil();
		RuntimeEngine.getStage().addChild(debugger);
		debugger.create();
		/*
		if ( RuntimeEngine.base!=null ) {
			RuntimeEngine.getStage().addChild(debugger);
		} else {
			throw "RuntimeEngine not initialized!";
		}
		*/
		#end
	}

	// }}}
	// {{{ public static function setLocation( x:Float, y:Float ) : Void
	/**
	* trace出力用ウィンドウの表示位置を指定します。
	*/
	public static function setLocation( x:Float, y:Float ) : Void
	{
		debugger.x = x;
		debugger.y = y;
	}

	// }}}
	// {{{ public function new() : Void
	/**
	* コンストラクタ
	*/
	public function new() : Void
	{
		super();
		mouseEnabled = false;
	}

	// }}}
	#if flash9
	// {{{ public function create() : Void
	/**
	* 内部関数です。
	*/
	public function create() : Void
	{
		w = 320;
		h = 240;
		isResizing = false;
		haxe.Log.trace = trace;
		// {{{ text field
		tf = new TextField();
		tf.type = TextFieldType.INPUT;
		tf.multiline = true;
		tf.border = true;
		tf.width  = w - 4;  //596;
		tf.height = h - 40; //80;
		tf.x = 2;
		tf.y = 20;
		// }}}
		sp1 = new Sprite();
		sp2 = new Sprite();
		sp3 = new Sprite();
		sp4 = new Sprite();
		sp5 = new Sprite();
		sp6 = new Sprite();
		// {{{ sp1 (background)
		// {{{ d1
		d1 = new Sprite();
		d1.graphics.beginFill( 0xCCCCCC, 1.0 );
		d1.graphics.drawRoundRect(0,0,w,h,5);
		d1.graphics.endFill();
		// }}}
		sp1.addChild(d1);
		// }}}
		// {{{ sp2 (top bar)
		// {{{ d2
		var d2:Sprite = new Sprite();
		d2.graphics.beginFill( 0x999999, 1.0 );
		d2.graphics.drawRoundRect(0,0,w-64,16,5);
		d2.graphics.endFill();
		// }}}
		sp2.addChild(d2);
		sp2.addEventListener( MouseEvent.MOUSE_DOWN, moveStartHandler );
		sp2.addEventListener( MouseEvent.MOUSE_UP,   moveEndHandler );
		sp2.x = 2;
		sp2.y = 2;
		// }}}
		// {{{ sp3 (clear button)
		// {{{ d3
		var d3:Sprite = new Sprite();
		d3.graphics.beginFill( 0x999999, 1.0 );
		d3.graphics.drawRoundRect(0,0,40,16,5);
		d3.graphics.endFill();
		// }}}
		// {{{ label
		var label:TextField = new TextField();
		var labelformat:TextFormat = new TextFormat();
		labelformat.align = TextFormatAlign.CENTER;
		label.defaultTextFormat = labelformat;
		label.text = "clear";
		label.width  = 36;  //596;
		label.height = 16; //80;
		label.x = 2;
		label.y = 0;
		// }}}
		// {{{ d3_2
		var d3_2:Sprite = new Sprite();
		d3_2.graphics.beginFill( 0x999999, 0.0 );
		d3_2.graphics.drawRoundRect(0,0,40,16,5);
		d3_2.graphics.endFill();
		// }}}
		sp3.addChild(d3);
		sp3.addChild(label);
		sp3.addChild(d3_2);
		sp3.addEventListener( MouseEvent.CLICK, clearHandler );
		sp3.x = w-60; //540;
		sp3.y = 2;
		// }}}
		// {{{ sp4 (close button)
		// {{{ d4
		var d4:Sprite = new Sprite();
		d4.graphics.beginFill( 0x999999, 1.0 );
		d4.graphics.drawRoundRect(0,0,16,16,5);
		d4.graphics.endFill();
		d4.graphics.lineStyle( 3, 0xFF6666 );
		d4.graphics.moveTo( 4, 4 );
		d4.graphics.lineTo( 12, 12 );
		d4.graphics.moveTo( 12, 4 );
		d4.graphics.lineTo( 4, 12 );
		// }}}
		sp4.addChild(d4);
		sp4.addEventListener( MouseEvent.CLICK, closeHandler );
		sp4.x = w-18; //582;
		sp4.y = 2;
		// }}}
		// {{{ sp5 (bottom bar)
		// {{{ d5
		var d5:Sprite = new Sprite();
		d5.graphics.beginFill( 0x999999, 1.0 );
		d5.graphics.drawRoundRect(0,0,w-22,16,5);
		d5.graphics.endFill();
		// }}}
		sp5.addChild(d5);
		sp5.addEventListener( MouseEvent.MOUSE_DOWN, moveStartHandler );
		sp5.addEventListener( MouseEvent.MOUSE_UP,   moveEndHandler );
		sp5.x = 2;
		sp5.y = h-18; //102;
		// }}}
		// {{{ sp6 (resize handler)
		// {{{ d6
		var d6:Sprite = new Sprite();
		d6.graphics.beginFill( 0x999999, 1.0 );
		d6.graphics.drawRoundRect(0,0,16,16,5);
		d6.graphics.endFill();
		// }}}
		sp6.addChild(d6);
		sp6.addEventListener( MouseEvent.MOUSE_DOWN, resizeStartHandler );
		sp6.addEventListener( MouseEvent.MOUSE_MOVE, resizeHandler );
		sp6.addEventListener( MouseEvent.MOUSE_UP,   resizeEndHandler );
		sp6.addEventListener( MouseEvent.ROLL_OUT,   resizeEndHandler );
		sp6.x = w-18; //582;
		sp6.y = h-18; //102;
		// }}}
		addChild(sp1);
		addChild(sp2);
		addChild(sp3);
		addChild(sp4);
		addChild(sp5);
		addChild(sp6);
		addChild(tf);
	}

	// }}}
	// {{{ public function resizeStartHandler( e:MouseEvent ) : Void
	/**
	* 内部関数です。
	*/
	public function resizeStartHandler( e:MouseEvent ) : Void
	{
		swapToTop();
		e.target.parent.startDrag(false);
		isResizing = true;
	}

	// }}}
	// {{{ public function resizeHandler( e:MouseEvent ) : Void
	/**
	* 内部関数です。
	*/
	public function resizeHandler( e:MouseEvent ) : Void
	{
		if ( isResizing ) {
			if ( sp6.x < (w-18) ) {
				sp6.x = w-18; //582;
			}
			if ( sp6.y < (h-18) ) {
				sp6.y = h-18; //102;
			}
			tf.width  = sp6.x + 14;
			tf.height = sp6.y - 22;
			sp4.x = sp6.x;
			sp5.y = sp6.y;
			update();
		}
	}

	// }}}
	// {{{ public function resizeEndHandler( e:MouseEvent ) : Void
	/**
	* 内部関数です。
	*/
	public function resizeEndHandler( e:MouseEvent ) : Void
	{
		isResizing = false;
		e.target.parent.stopDrag();
		if ( sp6.x < (w-18) ) {
			sp6.x = w-18; //582;
		}
		if ( sp6.y < (h-18) ) {
			sp6.y = h-18; //102;
		}
		tf.width  = sp6.x + 14;
		tf.height = sp6.y - 22;
		sp4.x = sp6.x;
		sp5.y = sp6.y;
		update();
	}

	// }}}
	#else
	// {{{ public function create() : Void
	/**
	* 内部関数です。
	*/
	public function create() : Void
	{
		w = 300;
		h = 120;
		isResizing = false;
		haxe.Log.trace = trace;
		tf = new TextField();
		sp1 = new Sprite();
		sp2 = new Sprite();
		sp3 = new Sprite();
		sp4 = new Sprite();
		sp5 = new Sprite();
		sp6 = new Sprite();
		sp1.mouseEnabled = false;
		addChild(sp1);
		addChild(tf);
		addChild(sp2);
		addChild(sp3);
		addChild(sp4);
		addChild(sp5);
		addChild(sp6);
		// {{{ text field
		tf.type = "input";
		tf.textfield.selectable = true;
		tf.multiline = true;
		tf.border = true;
		tf.width  = w - 4;  //596;
		tf.height = h - 40; //80;
		//tf.background = true;
		//tf.backgroundColor = 0xFFFFFF;
		tf.x = 2;
		tf.y = 20;
		// }}}
		// {{{ sp1 (background)
		// {{{ d1
		d1 = new Sprite();
		d1.mouseEnabled = false;
		sp1.addChild(d1);
		d1.graphics.beginFill( 0xCCCCCC );
		d1.graphics.drawRoundRect(0,0,w,h,5);
		d1.graphics.endFill();
		// }}}
		// }}}
		// {{{ sp2 (top bar)
		// {{{ d2
		var d2:Sprite = new Sprite();
		sp2.addChild(d2);
		d2.graphics.beginFill( 0x999999 );
		d2.graphics.drawRoundRect(0,0,w-64,16,5);
		d2.graphics.endFill();
		// }}}
		sp2.addEventListener( MouseEvent.MOUSE_DOWN, moveStartHandler );
		sp2.addEventListener( MouseEvent.MOUSE_UP,   moveEndHandler );
		sp2.x = 2;
		sp2.y = 2;
		// }}}
		// {{{ sp3 (clear button)
		// {{{ d3
		var d3:Sprite = new Sprite();
		sp3.addChild(d3);
		d3.graphics.beginFill( 0x999999 );
		d3.graphics.drawRoundRect(0,0,40,16,5);
		d3.graphics.endFill();
		// }}}
		// {{{ label
		var label:TextField = new TextField();
		sp3.addChild(label);
		var labelformat:TextFormat = new TextFormat();
		labelformat.align = "center";
		label.textfield.setTextFormat( labelformat );
		label.text = "clear";
		label.width  = 36;  //596;
		label.height = 16; //80;
		label.x = 2;
		label.y = 0;
		// }}}
		// {{{ d3_2
		var d3_2:Sprite = new Sprite();
		sp3.addChild(d3_2);
		d3_2.graphics.beginFill( 0x999999, 0.0 );
		d3_2.graphics.drawRoundRect(0,0,40,16,5);
		d3_2.graphics.endFill();
		// }}}
		sp3.addEventListener( MouseEvent.CLICK, clearHandler );
		sp3.x = w-60; //540;
		sp3.y = 2;
		// }}}
		// {{{ sp4 (close button)
		// {{{ d4
		var d4:Sprite = new Sprite();
		sp4.addChild(d4);
		d4.graphics.beginFill( 0x999999 );
		d4.graphics.drawRoundRect(0,0,16,16,5);
		d4.graphics.endFill();
		d4.graphics.lineStyle( 3, 0xFF6666 );
		d4.graphics.moveTo( 4, 4 );
		d4.graphics.lineTo( 12, 12 );
		d4.graphics.moveTo( 12, 4 );
		d4.graphics.lineTo( 4, 12 );
		// }}}
		sp4.addEventListener( MouseEvent.CLICK, closeHandler );
		sp4.x = w-18; //582;
		sp4.y = 2;
		// }}}
		// {{{ sp5 (bottom bar)
		// {{{ d5
		var d5:Sprite = new Sprite();
		sp5.addChild(d5);
		d5.graphics.beginFill( 0x999999 );
		d5.graphics.drawRoundRect(0,0,w-22,16,5);
		d5.graphics.endFill();
		// }}}
		sp5.addEventListener( MouseEvent.MOUSE_DOWN, moveStartHandler );
		sp5.addEventListener( MouseEvent.MOUSE_UP,   moveEndHandler );
		sp5.x = 2;
		sp5.y = h-18; //102;
		// }}}
		// {{{ sp6 (resize handler)
		// {{{ d6
		var d6:Sprite = new Sprite();
		sp6.addChild(d6);
		d6.graphics.beginFill( 0x999999 );
		d6.graphics.drawRoundRect(0,0,16,16,5);
		d6.graphics.endFill();
		// }}}
		sp6.addEventListener( MouseEvent.MOUSE_DOWN, resizeStartHandler );
		sp6.addEventListener( MouseEvent.MOUSE_MOVE, resizeHandler );
		sp6.addEventListener( MouseEvent.MOUSE_UP,   resizeEndHandler );
		sp6.addEventListener( MouseEvent.ROLL_OUT,   resizeEndHandler );
		sp6.x = w-18; //582;
		sp6.y = h-18; //102;
		// }}}
	}

	// }}}
	// {{{ public function resizeStartHandler( e:MouseEvent ) : Void
	/**
	* 内部関数です。
	*/
	public function resizeStartHandler( e:MouseEvent ) : Void
	{
		swapToTop();
		e.target.graphics.startDrag(false);
		isResizing = true;
	}

	// }}}
	// {{{ public function resizeHandler( e:MouseEvent ) : Void
	/**
	* 内部関数です。
	*/
	public function resizeHandler( e:MouseEvent ) : Void
	{
		if ( isResizing ) {
			if ( sp6.x < (w-18) ) {
				sp6.x = w-18; //582;
			}
			if ( sp6.y < (h-18) ) {
				sp6.y = h-18; //102;
			}
			tf.width  = sp6.x + 14;
			tf.height = sp6.y - 22;
			sp4.x = sp6.x;
			sp5.y = sp6.y;
			update();
		}
	}

	// }}}
	// {{{ public function resizeEndHandler( e:MouseEvent ) : Void
	/**
	* 内部関数です。
	*/
	public function resizeEndHandler( e:MouseEvent ) : Void
	{
		isResizing = false;
		e.target.graphics.stopDrag();
		if ( sp6.x < (w-18) ) {
			sp6.x = w-18; //582;
		}
		if ( sp6.y < (h-18) ) {
			sp6.y = h-18; //102;
		}
		tf.width  = sp6.x + 14;
		tf.height = sp6.y - 22;
		sp4.x = sp6.x;
		sp5.y = sp6.y;
		update();
	}

	// }}}
	#end
	// {{{ public function moveStartHandler( e:MouseEvent ) : Void
	/**
	* 内部関数です。
	*/
	public function moveStartHandler( e:MouseEvent ) : Void
	{
		swapToTop();
		startDrag(false);
	}

	// }}}
	// {{{ public function moveEndHandler( e:MouseEvent ) : Void
	/**
	* 内部関数です。
	*/
	public function moveEndHandler( e:MouseEvent ) : Void
	{
		stopDrag();
	}

	// }}}
	// {{{ public function clearHandler( e:MouseEvent ) : Void
	/**
	* 内部関数です。
	*/
	public function clearHandler( e:MouseEvent ) : Void
	{
		tf.text = "";
		e.stopImmediatePropagation();
	}

	// }}}
	// {{{ public function closeHandler( e:MouseEvent ) : Void
	/**
	* 内部関数です。
	*/
	public function closeHandler( e:MouseEvent ) : Void
	{
		visible = false;
		e.stopImmediatePropagation();
	}

	// }}}
	// {{{ public function swapToTop() : Void
	/**
	* 内部関数です。
	*/
	public function swapToTop() : Void
	{
		var s:Stage = RuntimeEngine.getStage();
		s.setChildIndex(this,s.numChildren-1);
	}

	// }}}
	// {{{ public function swapToBottom() : Void
	/**
	* 内部関数です。
	*/
	public function swapToBottom() : Void
	{
		var s:Stage = RuntimeEngine.getStage();
		s.setChildIndex(this,0);
	}

	// }}}
	// {{{ public function update() : Void
	/**
	* 内部関数です。
	*/
	public function update() : Void
	{
		d1.graphics.clear();
		d1.graphics.beginFill( 0xCCCCCC );
		d1.graphics.drawRoundRect(0,0,sp6.x+18,sp6.y+18,5);
		d1.graphics.endFill();
	}

	// }}}
	// {{{ public function trace(v : Dynamic, ?inf : haxe.PosInfos )
	/**
	* 内部関数です。
	*/
	public function trace(v : Dynamic, ?inf : haxe.PosInfos )
	{
		visible = true;
		swapToTop();
		var type = if( inf != null && inf.customParams != null ) inf.customParams[0] else null;
		if( type != "warn" && type != "info" && type != "debug" && type != "error" )
			type = if( inf == null ) "error" else "log";

		var infoText:String = (if( inf == null ) "" else inf.fileName + ":" + inf.lineNumber + " : ");

		var prefix:String = DateTools.format(Date.now(),"[%Y/%m/%d %H:%M:%S]") + " ";
		tf.text += prefix + infoText + v + "\n";
	}

	// }}}
}

